#include "./main_loop.h"
#include "./frame.h"
#include "./can_receiver.h"
#include "../pub_driver/cmd_can.h"
#include "../main_driver/cmd_uart.h"
#include "../utils/byte_alloc.h"
#include "../rtos/thread.h"
#include "../utils/log.h"


namespace conn {

using namespace pub_driver;
using namespace main_driver;

static ByteAlloc<1024> canByteAlloc;

Frame alloc_frame(const uint8_t *buf, uint8_t len) {
    uint8_t *p = canByteAlloc.alloc_next(len);
    memcpy(p, buf, len);
    return Frame(p, len);
}

void alloc_write(const uint8_t *buf, uint8_t len) {
    uint8_t *p = canByteAlloc.alloc_next(len);
    memcpy(p, buf, len);
    cmdUart->write(p, len);
}

template <uint8_t FRAME_SRC, uint32_t SIZE>
struct RecvHandler : public CANReceiver<RecvHandler<FRAME_DST, SIZE>, SIZE> {

    void on_recv_finish(const uint8_t *buf, uint32_t len) {
        if (!is_frame_valid(buf, len)) {
            return;
        }
        
    }
};

#ifdef APP_MAIN
static RecvHandler<addr::IPC, 128> ipcHandler;
#endif

static RecvHandler<addr::SELF, 128> myHandler;

#ifdef APP_MAIN

class UartRecvTask : public rtos::Thread<UartRecvTask, 1024, osPriorityHigh1>, public Object<UartRecvTask> {

public:
    void run() {
        Frame frame;
        for (;;) {
            cmdUart->recv_from(frame);
            
            if (frame.dst() != addr::SELF) {
                cmdCAN->write(frame.buf, frame.len);
                println("CAN数据转发");
                continue;
            } 

            switch (frame.type()) {
                case type::PING: cmdUart->write<type::PONG>(frame.src()); break;

            }
        }
    }
};

static UartRecvTask uartRecvTask;

#endif

void MainLoop::loop() {

#ifdef APP_MAIN
    uartRecvTask->start();
#endif

    CANFrame frame;
    for (;;) {
        cmdCAN->recv_can_frame(frame);

#ifdef APP_MAIN
        if (frame.src() == addr::SELF) {
            myHandler.on_recv(frame);
        } else {
            ipcHandler.on_recv(frame);
        }
#else
        myHandler.on_recv(frame);
#endif


    }
}

}
